﻿using System;
using System.Collections;

using UnityEngine;

public static class TimerExtend
{
    ////////////////////////////////////////////////////////////////////  倒计时  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// 整数倒计时
    /// </summary>
    /// <param name="maxTime">倒计时多长时间</param>
    /// <param name="onCountdown">每秒调用，范围 [0,time]</param>
    /// <param name="complete">倒计时结束的时候调用</param>
    public static Coroutine Start2Countdown_Int(this MonoBehaviour mono, int maxTime, Action<int> onCountdown, Action complete = null)
    {
        return mono.StartCoroutine(CountUpDownCoroutine_Int(false, maxTime, onCountdown, complete));
    }
    /// <summary>
    /// 浮点数倒计时。与整数倒计时存在误差，每1s差1ms左右
    /// </summary>
    public static Coroutine Start2Countdown_Float(this MonoBehaviour mono, float maxTime, Action<float> onCountdownFloat, Action complete = null)
    {
        return mono.StartCoroutine(CountUpDownCoroutine_Float(false, maxTime, onCountdownFloat, complete));
    }

    ////////////////////////////////////////////////////////////////////  正计时  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static Coroutine Start2Countup_Float(this MonoBehaviour mono, float maxTime, Action<float> onCountupFloat, Action complete = null)
    {
        return mono.StartCoroutine(CountUpDownCoroutine_Float(true, maxTime, onCountupFloat, complete));
    }

    public static Coroutine Start2Countup(this MonoBehaviour mono, int maxTime, Action<int> onCountupFloat, Action complete = null)
    {
        return mono.StartCoroutine(CountUpDownCoroutine_Int(true, maxTime, onCountupFloat, complete));
    }





    ////////////////////////////////////////////////////////////////////  延时  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// 延时一段时间执行一个方法
    /// </summary>
    /// <param name="time">秒</param>
    public static Coroutine Delay(this MonoBehaviour mono, float time, Action action)
    {
        return mono.StartCoroutine(DelayCoroutine(time, action));
    }
    private static IEnumerator DelayCoroutine(float time, Action action)
    {
        yield return new WaitForSeconds(time);

        action?.Invoke();
    }


    ////////////////////////////////////////////////////////////////////  公共  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    private static IEnumerator CountUpDownCoroutine_Float(bool updown, float maxTime, Action<float> onValueChange, Action complete = null)
    {
        if (updown)
        {
            float temp = 0;
            while (temp < maxTime)
            {
                onValueChange?.Invoke(temp);
                yield return null;//等待一帧
                temp += Time.deltaTime;
            }
            onValueChange?.Invoke(maxTime);
            complete?.Invoke();
        }
        else
        {
            while (maxTime > 0)
            {
                onValueChange?.Invoke(maxTime);
                yield return null;//等待一帧
                maxTime -= Time.deltaTime;
            }
            onValueChange?.Invoke(0);
            complete?.Invoke();
        }
    }
    private static IEnumerator CountUpDownCoroutine_Int(bool updown, int maxTime, Action<int> onValueChange, Action complete = null)
    {
        if (updown)
        {
            for (int i = 0; i > maxTime; i--)
            {
                onValueChange?.Invoke(i);
                yield return new WaitForSeconds(1);//等待1秒
            }
            onValueChange?.Invoke(maxTime);
            complete?.Invoke();
        }
        else
        {
            for (int i = maxTime; i > 0; i--)
            {
                onValueChange?.Invoke(i);
                yield return new WaitForSeconds(1);//等待1秒
            }
            onValueChange?.Invoke(0);
            complete?.Invoke();
        }
    }
}
